package mysql

import (
	"WebSvr/modules/common"

	"crypto/md5"
	"encoding/hex"
	"strings"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"

	"fmt"
	"strconv"

	"sync"

	_ "github.com/go-sql-driver/mysql"
)

type ServerInfo struct {
	Ip   string
	Name string
}

type DbWebAdmin struct {
	mapDbWebAdmin map[string]*ServerCfg //key:serverName
	mapDbUser     map[string]*UserCfg   //key:username
	mapLoginUser  map[string]*UserCfg   //key:ip
	sliceAnnounce []*AnnounceData
	Lock          sync.RWMutex
}

var gWebAdmin *DbWebAdmin

func newWebAdmin() {
	gWebAdmin = &DbWebAdmin{
		mapDbWebAdmin: make(map[string]*ServerCfg),
		mapDbUser:     make(map[string]*UserCfg),
		mapLoginUser:  make(map[string]*UserCfg),
		sliceAnnounce: make([]*AnnounceData, 0),
	}
}

func GetWebAdmin() *DbWebAdmin {
	return gWebAdmin
}

func (self *DbWebAdmin) InsertDefaultAdmin(name string, passwd string, bindip string) (bool, error) {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_WEBADMIN)
	var defaultCfg UserCfg
	defaultCfg.Id = 1
	defaultCfg.Name = name
	defaultCfg.Ip = bindip
	defaultCfg.Passwd = passwd
	defaultCfg.Access = int(common.ACCESS_ADMIN)
	defaultCfg.Other = "admin"
	if _, ok := self.mapDbUser[defaultCfg.Name]; ok {
		return true, nil
	} else {
		_, errInsert := dbObj.Insert(&defaultCfg)
		if errInsert == nil {
			dbObj.Commit()
			self.mapDbUser[defaultCfg.Name] = &defaultCfg
			return true, nil
		} else {
			dbObj.Rollback()
			fmt.Println(errInsert)
			beego.Error(errInsert)
			return false, errInsert
		}
	}

}

func (self *DbWebAdmin) LoadSql() {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_WEBADMIN)
	sqlbuf := "select * from server_cfg order by id;"
	slice_cfg := make([]ServerCfg, 0, 100)
	_, err := dbObj.Raw(sqlbuf).QueryRows(&slice_cfg)
	if err != nil {
		beego.Error(err)
		return
	}

	for _, serverCfg := range slice_cfg {
		var tmpCfg ServerCfg
		tmpCfg.Id = serverCfg.Id
		tmpCfg.Ip = serverCfg.Ip
		tmpCfg.Port = serverCfg.Port
		tmpCfg.Name = serverCfg.Name
		tmpCfg.Area = serverCfg.Area
		tmpCfg.NewServer = serverCfg.NewServer
		tmpCfg.ChannelId = serverCfg.ChannelId
		self.mapDbWebAdmin[tmpCfg.Name] = &tmpCfg
	}
}

func (self *DbWebAdmin) LoadAnnounceSql() {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_WEBADMIN)
	sqlbuf := "select * from announce_data order by id;"
	_, err := dbObj.Raw(sqlbuf).QueryRows(&self.sliceAnnounce)
	if err != nil {
		beego.Error(err)
		return
	}
}

func (self *DbWebAdmin) LoadAllUserInfo() {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_WEBADMIN)

	sqlbuf := "select * from user_cfg;"
	slice_user := make([]UserCfg, 0, 100)
	_, err := dbObj.Raw(sqlbuf).QueryRows(&slice_user)
	if err != nil {
		beego.Error(err)
		return
	}

	for _, userCfg := range slice_user {
		var tmpCfg UserCfg
		tmpCfg.Id = userCfg.Id
		tmpCfg.Ip = userCfg.Ip
		tmpCfg.Name = userCfg.Name
		tmpCfg.Passwd = userCfg.Passwd
		tmpCfg.Access = userCfg.Access
		tmpCfg.Other = userCfg.Other
		self.mapDbUser[tmpCfg.Name] = &tmpCfg
	}

}

//验证游服是否在mysql列表内
func (self *DbWebAdmin) AuthServer(serverInfo *ServerInfo) bool {
	self.Lock.RLock()
	defer self.Lock.RUnlock()
	key := serverInfo.Name
	if v, ok := self.mapDbWebAdmin[key]; ok {
		if v.Name == serverInfo.Name {
			return true
		}
	}
	return false
}

//获取大区名
func (self *DbWebAdmin) GetAreaName(serverInfo *ServerInfo) (bool, string, uint8, int64) {
	self.Lock.RLock()
	defer self.Lock.RUnlock()
	key := serverInfo.Name
	if v, ok := self.mapDbWebAdmin[key]; ok {
		if v.Name == serverInfo.Name {
			return true, v.Area, v.NewServer, int64(v.Port)
		}
	}
	return false, "", 0, 0
}

//测试获取所有大区名
func (self *DbWebAdmin) GetALLInfo() *map[string]*ServerCfg {
	self.Lock.RLock()
	defer self.Lock.RUnlock()
	return &self.mapDbWebAdmin
}

func (self *DbWebAdmin) AuthUserLogin(userName string, token string, md5Passwd string, clientIp string) (bool, *UserCfg) {
	/*var authUser UserCfg
	err := dbObj.QueryTable("user_cfg").Filter("name", userName).One(&authUser)
	if err != nil {
		fmt.Println(err)
		return false
	}
	fmt.Println(authUser)*/
	self.Lock.Lock()
	defer self.Lock.Unlock()
	if authUser, ok := self.mapDbUser[userName]; ok {
		//获取到的用户名+密码混合tokenMgr的token进行运算
		h := md5.New()
		h.Write([]byte(token + authUser.Passwd))
		cipherStr := h.Sum(nil)
		savePasswd := hex.EncodeToString(cipherStr)
		if strings.EqualFold(savePasswd, md5Passwd) {
			self.mapLoginUser[clientIp] = authUser
			return true, authUser
		}

	}

	return false, nil
}

func (self *DbWebAdmin) GetAccessByIp(clientIp string) (string, int) {
	self.Lock.RLock()
	defer self.Lock.RUnlock()
	if loginUser, ok := self.mapLoginUser[clientIp]; ok {
		return loginUser.Name, loginUser.Access
	}
	return "", 0
}

func (self *DbWebAdmin) CheckUserIpCfg(userName string, ip string) bool {
	self.Lock.RLock()
	defer self.Lock.RUnlock()
	//检查用户表里是否有ip配置，没有配置则任何ip都可以登录
	if userVal, ok := self.mapDbUser[userName]; ok {
		if userVal.Ip != "" {
			if strings.EqualFold(userVal.Ip, ip) {
				return true
			} else {
				return false
			}
		} else {
			return true
		}

	}
	return false
}

//验证客户端是否已经登录过
func (self *DbWebAdmin) AuthUserIsLogin(clientIp string) bool {
	if _, ok := self.mapLoginUser[clientIp]; ok {
		return true
	}
	return false
}

//获取所有的Server_cfg列表
func (self *DbWebAdmin) GetAllServerCfg() *[]common.S2WServerData {
	self.Lock.RLock()
	defer self.Lock.RUnlock()
	serverList_len := len(self.mapDbWebAdmin)
	dataSet := make([]common.S2WServerData, 0, serverList_len+1)
	for _, data := range self.mapDbWebAdmin {
		var s2WData common.S2WServerData
		s2WData.Id = data.Id
		s2WData.Ip = data.Ip
		s2WData.Name = data.Name
		s2WData.Area = data.Area
		s2WData.Port = data.Port
		s2WData.NewServer = int(data.NewServer)
		s2WData.ChanId = data.ChannelId
		dataSet = append(dataSet, s2WData)
	}
	return &dataSet
}

//获取服务器名
func (self *DbWebAdmin) GetAllServerName() *[]string {
	self.Lock.RLock()
	defer self.Lock.RUnlock()
	serverList_len := len(self.mapDbWebAdmin)
	nameSet := make([]string, 0, serverList_len+1)
	for _, data := range self.mapDbWebAdmin {
		nameSet = append(nameSet, data.Name)
	}
	return &nameSet
}

//保存serverCfg数据到数据库
func (self *DbWebAdmin) SaveServerCfg2mySql(syncW2SData common.S2WServerData) bool {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	serverCfg := ServerCfg{
		Ip:        syncW2SData.Ip,
		Port:      syncW2SData.Port,
		Name:      syncW2SData.Name,
		Area:      syncW2SData.Area,
		ChannelId: syncW2SData.ChanId,
		NewServer: uint8(syncW2SData.NewServer),
	}
	fmt.Println("SaveServerCfg2mySql serverCfg:")
	fmt.Println(serverCfg)
	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_WEBADMIN)

	if value, ok := self.mapDbWebAdmin[serverCfg.Name]; ok {
		//存在则是update
		serverCfg.Id = value.Id
		_, err := dbObj.Update(&serverCfg)
		if err != nil {
			fmt.Println(err)
			return false
		}
	} else {
		_, err := dbObj.Insert(&serverCfg)
		if err != nil {
			fmt.Printf("insert err:%v\n", err)
			return false
		}

	}

	self.mapDbWebAdmin[serverCfg.Name] = &serverCfg
	return true
}

//删除serverCfg数据到数据库
func (self *DbWebAdmin) DelServerCfg2mySql(syncW2SData common.S2WServerData) bool {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	serverCfg := ServerCfg{
		Ip:        syncW2SData.Ip,
		Port:      syncW2SData.Port,
		Name:      syncW2SData.Name,
		Area:      syncW2SData.Area,
		ChannelId: syncW2SData.ChanId,
		NewServer: uint8(syncW2SData.NewServer),
	}
	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_WEBADMIN)

	if value, ok := self.mapDbWebAdmin[serverCfg.Name]; ok {
		serverCfg.Id = value.Id
		_, err := dbObj.Delete(&serverCfg)
		if err != nil {
			return false
		}
		delete(self.mapDbWebAdmin, serverCfg.Name)
	} else {
		return false
	}

	return true

}

//获取所有的UserCfg列表
func (self *DbWebAdmin) GetAllUserCfg() *[]common.S2WUserData {
	self.Lock.RLock()
	defer self.Lock.RUnlock()
	serverList_len := len(self.mapDbUser)
	dataSet := make([]common.S2WUserData, 0, serverList_len+1)
	for _, data := range self.mapDbUser {
		var s2WUser common.S2WUserData
		s2WUser.Name = data.Name
		s2WUser.Ip = data.Ip
		s2WUser.Passwd = data.Passwd
		s2WUser.Access = data.Access
		s2WUser.Other = data.Other
		dataSet = append(dataSet, s2WUser)
	}
	return &dataSet
}

//保存userCfg数据到数据库
func (self *DbWebAdmin) SaveUserCfg2mySql(userData common.S2WUserData) bool {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	userCfg := UserCfg{
		Name:   userData.Name,
		Passwd: userData.Passwd,
		Ip:     userData.Ip,
		Access: userData.Access,
		Other:  userData.Other,
	}
	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_WEBADMIN)
	fmt.Printf("SaveUserCfg2mySql:%v\n", userCfg.Name)
	if userVal, ok := self.mapDbUser[userCfg.Name]; ok {
		//存在则是update
		userCfg.Id = userVal.Id
		_, err := dbObj.Update(&userCfg)
		if err != nil {
			beego.Error(err)
			return false
		}
	} else {
		_, err := dbObj.Insert(&userCfg)
		if err != nil {
			beego.Error(err)
			return false
		}

	}

	self.mapDbUser[userCfg.Name] = &userCfg
	return true
}

//删除userCfg数据到数据库
func (self *DbWebAdmin) DelUserCfg2mySql(userData common.S2WUserData) bool {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	userCfg := UserCfg{
		Name:   userData.Name,
		Ip:     userData.Ip,
		Passwd: userData.Passwd,
		Access: userData.Access,
		Other:  userData.Other,
	}

	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_WEBADMIN)

	if userVal, ok := self.mapDbUser[userCfg.Name]; ok {
		userCfg.Id = userVal.Id
		_, err := dbObj.Delete(&userCfg)
		if err != nil {
			beego.Error(err)
			return false
		}
		delete(self.mapDbUser, userCfg.Name)
		return true
	}

	return false

}

//退出登录
func (self *DbWebAdmin) LogOut(clientIp string) (string, int, bool) {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	if userVal, ok := self.mapLoginUser[clientIp]; ok {
		userName := userVal.Name
		access := userVal.Access
		delete(self.mapLoginUser, clientIp)
		return userName, access, true
	}
	return "", 0, false
}

/********************************处理公告*************************************************/
func (self *DbWebAdmin) GetAnnounce() string {
	self.Lock.RLock()
	defer self.Lock.RUnlock()
	if len(self.sliceAnnounce) != 0 {
		pData := self.sliceAnnounce[0]
		if pData != nil {
			return pData.Announce
		} else {
			return "未设置公告"
		}
	}

	return "未设置公告"

}
func (self *DbWebAdmin) UpdateAnnounce(announceText common.AnnounceText) bool {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	count := len(self.sliceAnnounce)
	if count > 0 {
		//公告只有一个，所以比较map内的公告和发来公告的时间，使用最新的内容替换
		stampSave := self.sliceAnnounce[0].Time
		var fstampSave float64
		fstampSave, _ = strconv.ParseFloat(stampSave, 64)
		var fstampNew float64
		fstampNew, _ = strconv.ParseFloat(announceText.SendTime, 64)
		if fstampSave < fstampNew {
			self.sliceAnnounce[0].Announce = announceText.Announce
			self.sliceAnnounce[0].Time = announceText.SendTime
			return self.updateAnnounce2Mysql(self.sliceAnnounce[0])
		} else {
			return false
		}
	} else {
		var announceData AnnounceData
		announceData.Id = 1
		announceData.Announce = announceText.Announce
		announceData.Time = announceText.SendTime
		self.sliceAnnounce = append(self.sliceAnnounce, &announceData)
		return self.insertAnnounce2Mysql(&announceData)
	}

}

func (self *DbWebAdmin) updateAnnounce2Mysql(data *AnnounceData) bool {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_WEBADMIN)
	//更新到数据库
	_, err := dbObj.Update(data)
	if err != nil {
		fmt.Printf("err:\v\n", err)
		return false
	}
	return true
}

func (self *DbWebAdmin) insertAnnounce2Mysql(data *AnnounceData) bool {
	self.Lock.Lock()
	defer self.Lock.Unlock()
	dbObj := orm.NewOrm()
	dbObj.Using(common.ALIAS_WEBADMIN)
	//更新到数据库
	_, err := dbObj.Insert(data)
	if err != nil {
		fmt.Printf("err:\v\n", err)
		return false
	}
	return true
}
